home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / graphics / pbspline.zip / bspline.c next >
C/C++ Source or Header  |  1994-05-10  |  5KB  |  216 lines

  1. /* pov-bspline v1.0 
  2.  * 
  3.  * 10 May 1994, Michael Mittelstadt.  (not responsible for ugly output)
  4.  *
  5.  * The spline algorithm is not of my own making, which is probably a
  6.  * Good Thing.  This program does a pretty good approx. of a bspline
  7.  * and outputs povray code given x,y,z triplets.
  8.  * 
  9.  * report all bugs and improvements to meek@alpha2.csd.uwm.edu
  10.  *
  11.  */
  12.  
  13.  
  14. #include <unistd.h>
  15. #include <math.h>
  16. #include <stdio.h>
  17.  
  18. #define VERSION 1.0
  19. #define CONTROL_MAX 1000    /* change these to suit your whims (or ram) */
  20. #define SPLINE_MAX 5000
  21.  
  22. int total, points, degree;
  23. double thick;
  24. short int include;
  25.  
  26. double rp[SPLINE_MAX][3];
  27. double dots[CONTROL_MAX][3];
  28.  
  29. static double U[50];
  30.  
  31. /* A quick gopher search turned up this subroutine.   -- MWM */
  32.  
  33. /* Returns a set of (m+1) spline curve points given a set of (n+1) control
  34.  * points.  (t-1) is the degree of the polynomial used for the B-splines.
  35.  * Cubic polynomials (i.e., t=4) are usually sufficient.  [3] designates
  36.  * (x,y,z).  For a discussion of the spline curve algorithm, see the book
  37.  * ``Computer Graphics'', Donald Hearn and M. Pauline Baker, Prentice-Hall,
  38.  * 1986, pp. 200-2.
  39.  */
  40.  
  41. void
  42. spline(controlpoints, n, curvepoints, m, t)
  43.      double controlpoints[][3];
  44.      int n;
  45.      double curvepoints[][3];
  46.      int m;
  47.      int t;
  48. {
  49.   int j, k;
  50.   double N(), temp, u;
  51.  
  52.   for (j = 0; j <= n + t; j++) {
  53.     if (j < t)
  54.       U[j] = 0.0;
  55.     else if (t <= j && j <= n)
  56.       U[j] = j - t + 1;
  57.     else
  58.       U[j] = n - t + 2;
  59.   }
  60.   for (j = 0; j <= m; j++) {
  61.     u = ((double) j / m) * (n - t + 2 - .00000001);
  62.     curvepoints[j][0] = curvepoints[j][1] = curvepoints[j][2] = 0.0;
  63.     for (k = 0; k <= n; k++) {
  64.       temp = N(k, t, u);
  65.       curvepoints[j][0] += controlpoints[k][0] * temp;
  66.       curvepoints[j][1] += controlpoints[k][1] * temp;
  67.       curvepoints[j][2] += controlpoints[k][2] * temp;
  68.     }
  69.   }
  70. }
  71.  
  72. static double
  73. N(k, t, u)
  74.      int k;
  75.      int t;
  76.      double u;
  77. {
  78.   double firstterm, secondterm;
  79.  
  80.   if (t == 1)
  81.     if (U[k] <= u && u < U[k + 1])
  82.       return 1.0;
  83.     else
  84.       return 0.0;
  85.   if (U[k + t - 1] - U[k] < 1.0e-10)    /* Test for zero with real #s */
  86.     firstterm = 0.0;
  87.   else
  88.     firstterm = ((u - U[k]) / (U[k + t - 1] - U[k])) * N(k, t - 1, u);
  89.   if (U[k + t] - U[k + 1] < 1.0e-10)
  90.     secondterm = 0.0;
  91.   else
  92.     secondterm = ((U[k + t] - u) / (U[k + t] - U[k + 1])) * N(k + 1, t - 1, u);
  93.   return firstterm + secondterm;
  94. }
  95.  
  96. void
  97. outputheader()
  98. {
  99.   printf("/* File generated by pov-bspline v%1.1f */\n", VERSION);
  100.   printf("\n\ncamera { location <0,0,-10>");
  101.   printf("\n         direction z up y right 4/3*x }");
  102.   printf("\n\nlight_source { <-1,1,-12> color rgb <1,1,1> }");
  103.   printf("\n\n#declare def_tex=texture {");
  104.   printf("\n       pigment { color rgb <0.8,0.75,0.5> } }\n\n");
  105. }
  106.  
  107. void
  108. putsphere(punkt)
  109.      double punkt[3];
  110. {
  111.   printf("    sphere { <%lf,%lf,%lf>,%lf }\n", punkt[0], punkt[1], punkt[2], thick);
  112. }
  113.  
  114. void
  115. putcone(punkt1, punkt2)
  116.      double punkt1[3], punkt2[3];
  117. {
  118.   printf("    cone { <%lf,%lf,%lf>,%lf,<%lf,%lf,%lf>,%lf }\n",
  119.      punkt1[0], punkt1[1], punkt1[2], thick,
  120.      punkt2[0], punkt2[1], punkt2[2], thick);
  121. }
  122.  
  123. int
  124. snarfnumbers()
  125. {
  126.   int i = 0;
  127.  
  128.   while (!feof(stdin)) {
  129.     scanf("%lf %lf %lf", &dots[i][0], &dots[i][1], &dots[i][2]);
  130.     i++;
  131.   }
  132.   i -= 2;
  133.  
  134.   fprintf(stderr, "Points input: %d\n\n", i + 1);
  135.   return (i);
  136. }
  137.  
  138. void
  139. outputstuff(total)
  140.      int total;
  141. {
  142.   int i;
  143.  
  144.   if (!include)
  145.     outputheader();
  146.  
  147.   spline(dots, total, rp, (points * total), 3);
  148.   printf("#declare spline_obj = union {\n");
  149.   putsphere(rp[0]);
  150.   for (i = 1; i < (points * total) + 1; i++) {
  151.     putsphere(rp[i]);
  152.     putcone(rp[i - 1], rp[i]);
  153.   }
  154.   printf("} // spline_obj\n\n");
  155.   if (!include)
  156.     printf("\nobject { spline_obj texture { def_tex } }\n\n");
  157. }
  158.  
  159. main(argc, argv)
  160.      int argc;
  161.      char **argv;
  162. {
  163.   int c;
  164.   extern char *optarg;
  165.  
  166.   thick = 1.0;
  167.   points = 5;
  168.   degree = 4;
  169.   include = 0;
  170.  
  171.   while (1) {
  172.     c = getopt(argc, argv, "it:n:hp:");
  173.     if (c == -1)
  174.       break;
  175.     if (c == 'h') {
  176.       printf("syntax: bspline [options] < infile > whatever.pov\n");
  177.       printf("version: %1.1f\n", VERSION);
  178.       printf("options: -h   - This help.\n");
  179.       printf("         -i   - make a pov include file, not a pov scene file.\n");
  180.       printf("         -t n - Make spline n thickness. (default 1.0)\n");
  181.       printf("         -n n - Use n points per control point. (default 5)\n");
  182.       printf("         -p n - Degree of polynomial (2-6, default 4)\n");
  183.       printf("\ninfile should contain only a list of x,y,z points to influence the b-spline.\n\n");
  184.       exit(2);
  185.     }
  186.     if (c == 'p') {
  187.       degree = atoi(optarg);
  188.       if (degree < 2 || degree > 6) {
  189.     fprintf(stderr, "bspline: Invalid polynomial degree, should be in range 2-6\n");
  190.     exit(3);
  191.       }
  192.     }
  193.     if (c == 'n') {
  194.       points = atoi(optarg);
  195.       if (points < 1 || points > 1000) {
  196.     fprintf(stderr, "bspline: Invalid number of points : %d.\n", points);
  197.     exit(4);
  198.       }
  199.     }
  200.     if (c == 't') {
  201.       sscanf(optarg, "%lf", &thick);
  202.       if (thick <= 0) {
  203.     fprintf(stderr, "bspline: Invalid spline thickness.\n");
  204.     exit(5);
  205.       }
  206.     }
  207.     if (c == 'i')
  208.       include = 1;
  209.   }
  210.   fprintf(stderr, "pov-bspline version %1.1f - 1994, Michael Mittelstadt\n", VERSION);
  211.   fprintf(stderr, "Thickness : %lf\nPoints per control point : %d\n",
  212.       thick, points);
  213.   fprintf(stderr, "Polynomial Degree : %d\n", degree);
  214.   outputstuff(snarfnumbers());
  215. }
  216.